//（1）数据的监听
//（2）依赖的收集    
//       依赖收集的原因：当发现数据变化后，需要对页面进行更新
//       在程序收集之前需要对templete进行遍历收集，找出和数据有依赖的东西，收集保存下来，需要更新的时候进行处理
//       两个对象，一个是dep  和  watcher
class KVue {
   constructor(options) {
       this.$options = options
       //数据响应化
       this.$data = this.$options.data
       //遍历数据，所有的数据都进行get和set的遍历
       this.observe(this.$data) 
       new Compile(options.el, this)
       //created 执行
       if(options.created) {
            options.created.call(this)
       }
   }
   //对所有的数据进行观察和监听
   observe(value) {
       if(!value || typeof value !== 'object') {
           return
       }
       Object.keys(value).forEach(key => {
           this.defineReactive(value,key,value[key])
           //代理data中的属性到vue实例上
           this.proxyData(key)
       })
   }
   //数据的响应化
   defineReactive(obj, key, val) {
       this.observe(val)  //递归解决数据格式的问题，对象里面包含对象
        //模拟一下watcher的创建过程
       const dep = new Dep()
       Object.defineProperty(obj, key, {
           get() {//如果是调用，直接返回val
               Dep.target && dep.addDep(Dep.target)
               return val
           },
           set(newVal) {
               if(newVal === val) {
                   return
               }
               val = newVal   //key的值发生了变化，此时需要更新视图了
               dep.notify()
           }
       })
   }
   proxyData(key) {
        Object.defineProperty(this, key, {
            get() {
                //this[key]    相当于   this.$data[key]
                return this.$data[key]
            },
            set(newVal) {
                this.$data[key] = newVal
            }
        })
   }
}

//用来管理watcher 的，是一个观察者的的管家
class Dep {  
   constructor() {
       this.deps = [] //存储若干个依赖，一个watcher对应一个属性
   }
   addDep(dep) {  //添加依赖的方法的
       this.deps.push(dep)
   }

   notify() {  //通知所有的依赖，做更新
       this.deps.forEach(item => {  //遍历所有的东西，进行更新
           item.update()
       })
   }
}
//用来做调用更新的一个东西
class Watcher { 
   constructor(vm, key, cb) {
       this.vm = vm
       this.key = key
       this.cb = cb
       //将当前的Watcher实例指定到Dep静态的target    ---> 每次new Watcher()时，都会给Dep.target赋予一个new Watcher()出来的对象
       Dep.target = this
       //
       this.vm[this.key]    //触发getter，添加依赖
       Dep.target = null    //置空
   }
   update() {
       this.cb.call(this.vm, this.vm[this.key])
    }
}

